package com.xm.xmwa1706090.service.netty;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.xm.xm.dto.ResultDto;
import com.xm.xm.util.DateUtils;
import com.xm.xmwa1706090.service.config.CMD;
import com.xm.xmwa1706090.service.model.SocketEntity;
import com.xm.xmwa1706090.service.service.impl.GatewayService;
import com.xm.xmwa1706090.service.util.CodeUtil;
import com.xm.xmwa1706090.service.util.HexCodeUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @Company 杭州新苗网络科技有限公司
 * @Author : loysen
 * @DateTime：2017年6月16日 下午1:23:10
 * @Description : { 消息处理 }
 *  对于消息的回应处理
 */
@Component
public class DeviceTCPServerHandler extends SimpleChannelInboundHandler<SocketEntity> {

	Logger logger = LoggerFactory.getLogger(DeviceTCPServerHandler.class);


	ReentrantLock  lock = new ReentrantLock();

	/**
	 * ChannelGroup 保存channel tcp/ip 的唯一标识
	 */
	static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

	/**
	 *
	 * @Author loysen
	 * @Data_Time 2017年4月22日 下午5:32:08
	 * @Description {发送消息给所有设备}
	 * @param entity
	 */
	public static void SendMsgToALL(SocketEntity entity) {
		System.out.println(" FFFFFFFFFFFFFFFF  服务端单独推送服务 发送请求 HHHHHHHHHHHHHHHHHH");
		channels.writeAndFlush(entity.EnCode());
	}

	/**
	 * netty 服务器 接收消息
	 * */
	@Override
	public void messageReceived(ChannelHandlerContext ctx, SocketEntity entity) {
		boolean is_send = true;
		SocketEntity socketResult = new SocketEntity();
		lock  = new ReentrantLock();
		lock.lock();
		try {
	/*
		 * 返回Entity的实体，说明 CRC校验通过,下面进行业务逻辑编写根据不同CMD命令，执行不同的操作
		 */
			switch (CodeUtil.HexStringToInt(entity.getCmd())) {
//				case CMD.LOGIN_TO_CLOUD :  //停车场服务器注册到云平台
//					ResultDto resultDto = duoduoUserService.login(entity);
//					socketResult.setParam(String.valueOf(resultDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.LOGIN_TO_CLOUD));
//					socketResult.setType(String.valueOf(0002));
//					is_send = true;
//					break;
//				case CMD.HB_TO_CLOUD:// 停车场服务器发心跳包到云
//					ResultDto cloudResultDto = duoduoUserService.hbToCloud(entity);
//					socketResult.setParam(String.valueOf(cloudResultDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.HB_TO_CLOUD));
//					socketResult.setType(String.valueOf(0002));
//					is_send = true;
//					break;
//				case CMD.CMD_TCC_PARKINFO_SYN:// 停车信息同步
//					ResultDto parkInfoResultDto = duoduoPassLogService.parkInfoSyn(entity);
//					socketResult.setParam(String.valueOf(parkInfoResultDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.CMD_TCC_PARKINFO_SYN));
//					socketResult.setType(String.valueOf(0002));
//					is_send = true;
//					break;
//				case CMD.CMD_TCC_PAYEDINFO_SYN:// 非终端缴费信息同步
//					ResultDto payResultDto = duoduoPaymentRecordsService.payInfoSyn(entity);
//					socketResult.setParam(String.valueOf(payResultDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.CMD_TCC_PAYEDINFO_SYN));
//					socketResult.setType(String.valueOf(0002));
//					is_send = true;
//					break;
//				case CMD.CMD_TCC_NOTICE_CAROUT:// 车辆出场通知
//					ResultDto carOutResultDto = duoduoPassLogService.carOutInfo(entity);
//					socketResult.setParam(String.valueOf(carOutResultDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.CMD_TCC_NOTICE_CAROUT));
//					socketResult.setType(String.valueOf(0002));
//					is_send = true;
//					break;
//				case CMD.CMD_CLOUD_GET_PARK_INFO:// 停车场信息查询
//					ResultDto getParkInfoDto = duoduoParkService.getParkInfo(entity);
//					socketResult.setParam(String.valueOf(getParkInfoDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.CMD_CLOUD_GET_PARK_INFO));
//					socketResult.setType(String.valueOf(0001));
//					is_send = false;
//					break;
//				case CMD.CMD_CLOUD_GET_PAY_INFO : 	//41停车费查询
//					JSONObject jsonObject = JSONObject.fromObject(entity.getParam());
//					EntityWrapper entityWrapper = new EntityWrapper();
//					entityWrapper.where(" accountNo = {0} " ,jsonObject.getString("accountNo") );
//					DuoduoPayInfo duoduoPayInfo = duoduoPayInfoService.selectOne(entityWrapper) ;
//					boolean b = true;
//					if(duoduoPayInfo == null) {
//						duoduoPayInfo = new DuoduoPayInfo();
//						b = false;
//					}
//					duoduoPayInfo.setAccountNo(jsonObject.getString("accountNo"));
//					duoduoPayInfo.setParkId(Integer.parseInt(entity.getTermid()));
//					duoduoPayInfo.setMediaNo(jsonObject.getString("mediaNo"));
//					duoduoPayInfo.setInputTime(jsonObject.getString("inputTime"));
//					duoduoPayInfo.setCurrentTime(jsonObject.getString("currentTime"));
//					duoduoPayInfo.setTimeCount(jsonObject.getInt("timeCount"));
//					duoduoPayInfo.setAmout(jsonObject.getInt("amount"));
//					duoduoPayInfo.setDisAmount(jsonObject.getInt("discAmount"));
//					duoduoPayInfo.setPaidAmount(jsonObject.getInt("paidAmount"));
//					duoduoPayInfo.setSettType(jsonObject.getString("settType"));
//					duoduoPayInfo.setResult(jsonObject.getString("result"));
//					duoduoPayInfo.setRsv1(jsonObject.getString("rsv1"));
//					duoduoPayInfo.setRsv2(jsonObject.getString("rsv2"));
//					if(b)
//						duoduoPayInfoService.updateById(duoduoPayInfo);
//					else
//						duoduoPayInfoService.insert(duoduoPayInfo);
//					break;
//				case CMD.CMD_CLOUD_GET_PAY_NOTICE:// 缴费通知
//					JSONObject noticeJson = JSONObject.fromObject(entity.getParam());
//					EntityWrapper noticeEntity = new EntityWrapper();
//					noticeEntity.where(" accountNo = {0} " ,noticeJson.getString("accountNo") );
//					DuoduoPayNotice duoduoPayNotice = duoduoPayNoticeService.selectOne(noticeEntity) ;
//					boolean noticeBool = true;
//					if(duoduoPayNotice == null) {
//						duoduoPayNotice = new DuoduoPayNotice();
//						noticeBool = false;
//					}
//					duoduoPayNotice.setAccountNo(noticeJson.getString("accountNo"));
//					duoduoPayNotice.setResult(noticeJson.getString("result"));
//					if(noticeBool)
//						duoduoPayNoticeService.updateById(duoduoPayNotice);
//					else
//						duoduoPayNoticeService.insert(duoduoPayNotice);
//					break;
//				case CMD.CMD_CLOUD_GET_PAID_STATE:// 缴费通知状态查询
//					ResultDto getPaidStateDto = duoduoUserService.getPaidState(entity);
//					socketResult.setParam(String.valueOf(getPaidStateDto.getData()));
//					socketResult.setCmd(String.valueOf(CMD.CMD_CLOUD_GET_PAID_STATE));
//					socketResult.setType(String.valueOf(0001));
//					is_send = false;
//					break;
				default:
					System.out.println("default ----->socketEntity  :\n" + entity.toString());
					break;
			}
			if (is_send) {
				// 返回响应Entity
				entity.setVersion( HexCodeUtils.tenToHexPadLeft( 1,2)+HexCodeUtils.tenToHexPadLeft( 0,2) );
				entity.setCmd(HexCodeUtils.tenToHexPadLeft( 1,4) );
				entity.setType(HexCodeUtils.tenToHexPadLeft( 1,4) );
				//////////////////////
				entity.setTermid(HexCodeUtils.tenToHexPadLeft( 1,24) );
				entity.setFlag(HexCodeUtils.tenToHexPadLeft( 0,8) );
				entity.setSeq(HexCodeUtils.tenToHexPadLeft( 0,8) );

				int lengths = (2+2+2+12+4 ) * 2  + entity.getParam().getBytes().length ;
				entity.setLength(HexCodeUtils.tenToHexPadLeft( lengths,4) );

				// CRC16校验
				byte[] crc16_data = CodeUtil.hexStringToBytes(entity.getStart()
						+ entity.getLength() + entity.getVersion()
						+ entity.getCmd() + entity.getType() + entity.getTermid()
						+ entity.getSeq() +entity.getFlag() + entity.getParam() +entity.getEnd() );
				String crc16 = CodeUtil.CRC16Table(crc16_data);
				crc16 = crc16.substring(0, 4);

				entity.setCrc16(crc16);
				byte[] bytes = entity.EnCode();
				ctx.writeAndFlush(bytes);
				System.out.println("服务端回应客户端请求 -------- "+ DateUtils.getNowDateTime() + "\n" +entity.toString());
			}

		}finally {
			lock.unlock();
		}
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		// A closed channel will be removed from ChannelGroup automatically
		logger.info("A closed channel will be removed from ChannelGroup automatically: "+ctx);
		channels.add(ctx.channel());
		//-- 记录进 本地MAP 本地缓存
		String uuid = ctx.channel().id().asLongText();
		GatewayService.addGatewayChannel(uuid, ctx);
		System.out.println("a new connect come in: " + uuid);

	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		GatewayService.removeGatewayChannel(ctx.channel().id().asLongText());
		ctx.close();
	}


}
